 
#ifndef __RSP_S_UPDATE__HEADER_FILE__
#define __RSP_S_UPDATE__HEADER_FILE__

#include "coid/comm/commtypes.h"
#include "coid/comm/dynarray.h"
#include "coid/comm/binstream/binstream.h"

#include "update.h"
#include "rsp_def.h"


using namespace coid;

struct rsp_s_connector;


////////////////////////////////////////////////////////////////////////////////
///Global RSP server settings
struct rsp_s_settings : rsp_settings
{
    uint _nkickoff_frames;          ///< number of frames to wait before kicking off the server
    uint _nkickoffstart_frames;     ///< number of frames to wait before kicking off the server when connecting

    uint _maxpacketsize;            ///< max packet size to send
    uint _maxpacketperframe;        ///< max avg throughput per frame

    //uint _wrk_cmdmask;
    //dynarray<uchar> _wrk_cmdbuf;

    dynarray<ushort> _wrk_cmdlengths;


    void set_params( uint ntrailing, uint nwaiting )
    {
        rsp_settings::init( ntrailing, nwaiting );

        _nkickoff_frames = 200;
        _nkickoffstart_frames = _ntrailing + 400;

        // kbps 
        _maxpacketperframe = 96;
        _maxpacketperframe = (_maxpacketperframe * 1024 * _Timer.get_period_usec()) / 8 / 1000000;
        _maxpacketsize = 1200;
    }
};

extern rsp_s_settings  RSPS_SETTINGS;




////////////////////////////////////////////////////////////////////////////////
///Object containing the streamed updates, used by server
class rsp_s_update
{
public:
    int _ntrailskip;                ///< trailing commands to skip (already acked by the client)
    uint _ackstateid;

    binstream* _bin;                ///< data stream for updates
    rsp_s_connector* _ctrl;

    bool full_update() const        { return _ntrailskip == -1; }


    ///Create rsp_update object on the server
    rsp_s_update( rsp_s_connector* ctrl, binstream* bout, uint ackstateid )
    {
        _ntrailskip = RSP_SETTINGS.active_frame() - ackstateid;

        if( _ntrailskip == 0  ||  _ntrailskip > (int)RSP_SETTINGS._ntrailing )
            _ntrailskip = -1;
        else
            _ntrailskip = RSP_SETTINGS._ntrailing - _ntrailskip;

        _ctrl = ctrl;
        _bin = bout;
        _ackstateid = ackstateid;
    }

    rsp_s_update( rsp_s_connector* ctrl )
    {
        _ctrl = ctrl;
        _bin = 0;
        _ackstateid = 0;
        _ntrailskip = -1;
    }

    rsp_s_update( const rsp_s_update& src )
    {
        _ctrl = src._ctrl;
        _bin = src._bin;
        _ackstateid = src._ackstateid;
        _ntrailskip = src._ntrailskip;
    }

};

#endif //__RSP_S_UPDATE__HEADER_FILE__
